﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using LuxDiner.Model.Orders;
using LuxDiner.Model.Members;
using LuxDiner.Model.Products;
using LuxDiner.Model.Financial;
using Utils;
namespace LuxDiner.Command.Orders
{
    public class ProductOrderCommand
    {
        public static ProductOrderModel NewOrder(ProductOrderModel order) 
        {
            if (order != null)
            {
                using (DBCentre db = new DBCentre())
                {
                    var orderMethod = (OrderMethod)Enum.Parse(typeof(OrderMethod), order.Method.ToString());
                    order.OrderNo = Comm.Orders.CreateOrderNo(db, orderMethod);
                    var dOrder = Convertor.ConvertFrom<order_product, ProductOrderModel>(order);
                    var dItems = Convertor.ConvertFromCollection<order_product_details, ProductOrderDetailModel>(order.Items);
                    foreach (var it in dItems)
                        dOrder.order_product_details.Add(it);
                    db.DataContext.order_product.Add(dOrder);

                    var dealOrder = db.DataContext.order_deal.FirstOrDefault(p => p.ID == order.AssociatedDealID);

                    #region 修改交易单据的状态 判断是否已经完成库存操作
                    var deal_items = dealOrder.order_deal_details.ToList();
                    var pro_orders = dealOrder.order_product.ToList();
                    var hasDone=true;
                    foreach (var it in order.Items)
                    {
                        deal_items.ForEach(p =>
                        {
                            decimal qua = 0;
                            pro_orders.ForEach(o =>
                            {
                                qua += o.order_product_details.Where(r => r.ProductID == p.ProductID).Sum(r => r.Quantity);
                            });
                            if (p.Quantity > qua)
                                hasDone = false;
                        });
                    }
                    dealOrder.OrderStatus = (int)(hasDone ? OrderStatus.Done : OrderStatus.Processing);
                    #endregion
                    
                    #region 插入库存表
                    foreach (var it in order.Items)
                    {
                        var balance = it.Quantity;
                        var repertory = db.DataContext.repertories.Where(p => p.ProductID == it.ProductID && p.HouseID == order.HouseID && p.Retention==it.Retention).OrderByDescending(p => p.ID).FirstOrDefault();
                        
                        if (order.Method == (int)Model.Orders.OrderMethod.CK)
                        {
                            it.Quantity *= -1;
                            if (repertory == null || repertory.Balance + it.Quantity < 0)
                                throw new LuxDinerException(string.Format("{0}-库存不足", it.Product.ProductName));
                        }

                        if (repertory != null)
                            balance = repertory.Balance + it.Quantity;
                        
                        #region 计算库存价值
                        decimal finalCost = 0;
                        if (order.Method == (int)OrderMethod.RK)
                        {//如果是入库
                            if (dealOrder.Method == (int)OrderMethod.CG)
                                finalCost += dealOrder.order_deal_details.FirstOrDefault(p => p.ProductID == it.ProductID).UnitPrice * it.Quantity;
                            else if (dealOrder.Method == (int)OrderMethod.XT)
                            {
                                var a = db.DataContext.order_deal_details.Where(p => p.ProductID == it.ProductID && p.order_deal.Method == (int)OrderMethod.CG).OrderByDescending(p => p.ID).FirstOrDefault();
                                if (a != null)
                                    finalCost = a.UnitPrice * it.Quantity;
                            }
                            if (it.CostMoney > 0)
                                finalCost += it.CostMoney;
                            if (repertory != null)
                                finalCost += repertory.FinalCost;
                        }
                        else
                        {//如果是出库
                            var price = repertory.FinalCost / repertory.Balance;
                            finalCost = price * balance;
                        }
                        #endregion

                        db.DataContext.repertories.Add(new repertory()
                        {
                            OrderNo = order.OrderNo,
                            ProductID = it.ProductID,
                            Quantity = it.Quantity,
                            Balance = balance,
                            Description = order.Method == (int)Model.Orders.OrderMethod.RK ? "入库" : "出库",
                            CreatedOn = order.NoteDate,
                            Method = order.Method,
                            HouseID = order.HouseID,
                            Retention = it.Retention,
                            FinalCost = finalCost
                        });
                    }
                    #endregion

                    db.DataContext.SaveChanges();
                    order.ID = dOrder.ID;
                    return order;
                }
            }
            return null;
        }
        /// <summary>
        /// 查询单据列表
        /// </summary>
        /// <param name="sea"></param>
        /// <returns></returns>
        public static ProductOrderCollection GetOrders(ProductOrderQuery sea)
        {
            var result = new ProductOrderCollection();
            using (DBCentre db = new DBCentre())
            {
                IQueryable<order_product> q = db.DataContext.order_product;
                if (sea != null)
                {
                    if (!string.IsNullOrEmpty(sea.OrderNo))
                        q = q.Where(p => p.OrderNo == sea.OrderNo);
                    if (sea.OperatorUserID > 0)
                        q = q.Where(p => p.OperatorUserID == sea.OperatorUserID);
                    if (sea.HouseID > 0)
                        q = q.Where(p => p.HouseID == sea.HouseID);
                    if (sea.OrderDateBefore != null)
                        q = q.Where(p => p.NoteDate.CompareTo(sea.OrderDateBefore.Value) >= 0);
                    if (sea.OrderDateAfter != null)
                        q = q.Where(p => p.NoteDate.CompareTo(sea.OrderDateAfter.Value) <= 0);
                    if (sea.Method > 0)
                        q = q.Where(p => p.Method == sea.Method);
                    if (sea.CustomerID > 0)
                        q = q.Where(p => p.order_deal.CustomerID == sea.CustomerID);
                    if (sea.ProductID > 0)
                        q = q.Where(p => p.order_product_details.Any(o => o.ProductID == sea.ProductID));
                }
                var n = q.Count();
                if (n > 0)
                {
                    q = q.OrderByDescending(p => p.ID);
                    if (sea != null && sea.PageSize > 0)
                        q = q.Skip(sea.PageSize * sea.PageIndex).Take(sea.PageSize);
                    var lst = q.ToList();
                    result = Convertor.ConvertCollection<ProductOrderModel, order_product, ProductOrderCollection>(lst);
                    result.TotalRecordsCount = n;
                    foreach (var m in result)
                    {
                        var d = lst.Find(p => p.OrderNo == m.OrderNo);
                        if (sea.GetHouse)
                            m.Warehouse = Convertor.ConvertTo<WarehouseModel, warehouse>(d.warehouse);
                        if (sea.GetItems)
                            m.Items = Convertor.ConvertCollection<ProductOrderDetailModel, order_product_details, ProductOrderDetailCollection>(d.order_product_details);
                        if (sea.GetDealOrder && d.order_deal!=null)
                            m.AssociatedDealOrder = Convertor.ConvertTo<DealOrderModel, order_deal>(d.order_deal);
                    }
                }
            }
            return result;
        }

        public static ProductOrderModel GetOrder(string orderNo)
        {
            if (!string.IsNullOrEmpty(orderNo))
            {
                using (DBCentre db = new DBCentre())
                {
                    var d = db.DataContext.order_product.FirstOrDefault(p => p.OrderNo == orderNo);
                    if (d != null)
                    {
                        var m = Convertor.ConvertTo<ProductOrderModel, order_product>(d);
                        m.Items = Convertor.ConvertCollection<ProductOrderDetailModel, order_product_details, ProductOrderDetailCollection>(d.order_product_details);
                        m.Warehouse = Convertor.ConvertTo<WarehouseModel, warehouse>(d.warehouse);
                        foreach (var o in m.Items)
                        {
                            var di = d.order_product_details.FirstOrDefault(p => p.ID == o.ID);
                            o.Product = Convertor.ConvertTo<ProductModel, product>(di.product);
                        }
                        return m;
                    }
                }
            }
            return null;
        }
        /// <summary>
        /// 存盘调拨
        /// </summary>
        /// <param name="order"></param>
        /// <param name="targetHouseID"></param>
        /// <returns></returns>
        public static ProductOrderModel SetBalance(ProductOrderModel order, int targetHouseID = 0)
        {
            if (order != null)
            {
                using (DBCentre db = new DBCentre())
                {
                    var orderMethod = (OrderMethod)Enum.Parse(typeof(OrderMethod), order.Method.ToString());
                    order.OrderNo = Comm.Orders.CreateOrderNo(db, orderMethod);
                    if (order.Method == (int)Model.Orders.OrderMethod.TB)
                        order.Description = "调拨出";
                    var dOrder = Convertor.ConvertFrom<order_product, ProductOrderModel>(order);
                    var dItems = Convertor.ConvertFromCollection<order_product_details, ProductOrderDetailModel>(order.Items);
                    foreach (var it in dItems)
                        dOrder.order_product_details.Add(it);
                    db.DataContext.order_product.Add(dOrder);

                    #region 插入库存表
                    if (order.Method == (int)Model.Orders.OrderMethod.PC)
                    {
                        foreach (var it in order.Items)
                        {
                            var repertory = db.DataContext.repertories.Where(p => p.ProductID == it.ProductID && p.HouseID == order.HouseID && p.Retention == it.Retention).OrderByDescending(p => p.ID).FirstOrDefault();
                            var balance = it.Quantity;
                            balance += repertory == null ? 0 : repertory.Balance;
                            if (balance < 0)
                                throw new LuxDinerException(string.Format("{0}-库存不足", it.Product.ProductName));

                            #region 计算库存价值
                            decimal finalCost = it.CostMoney;
                            if (repertory != null)
                                finalCost += repertory.FinalCost;
                            #endregion

                            db.DataContext.repertories.Add(new repertory()
                            {
                                OrderNo = order.OrderNo,
                                ProductID = it.ProductID,
                                Quantity = it.Quantity,
                                Balance = balance,
                                Description = string.IsNullOrEmpty(order.Description) ? "盘存单" : order.Description,
                                CreatedOn = order.NoteDate,
                                Method = order.Method,
                                HouseID = order.HouseID,
                                Retention = it.Retention,
                                FinalCost = finalCost
                            });
                        }
                    }
                    else
                    {
                        var newOrder = Convertor.ConvertFrom<order_product, ProductOrderModel>(order);
                        newOrder.OrderNo = string.Format("TB-{0}", long.Parse(order.OrderNo.Replace("TB-", "")) + 1);
                        newOrder.Description = "调拨入";
                        newOrder.HouseID = targetHouseID;
                        var newItems = Convertor.ConvertFromCollection<order_product_details, ProductOrderDetailModel>(order.Items);
                        foreach (var it in newItems)
                            newOrder.order_product_details.Add(it);
                        db.DataContext.order_product.Add(newOrder);

                        foreach (var it in order.Items)
                        {
                            var repertory = db.DataContext.repertories.Where(p => p.ProductID == it.ProductID && p.HouseID == order.HouseID && p.Retention == it.Retention).OrderByDescending(p => p.ID).FirstOrDefault();
                            if (repertory == null || repertory.Balance - it.Quantity < 0)
                                throw new LuxDinerException(string.Format("{0}-库存不足", it.Product.ProductName));
                            var newRepertory = db.DataContext.repertories.Where(p => p.ProductID == it.ProductID && p.HouseID == targetHouseID && p.Retention == it.Retention).OrderByDescending(p => p.ID).FirstOrDefault();

                            var balance = repertory.Balance - it.Quantity;
                            decimal finalCost = repertory.FinalCost - it.CostMoney;

                            var newBalance = it.Quantity;
                            decimal newFinalCost = it.CostMoney;
                            if (newRepertory != null)
                            {
                                newBalance += newRepertory.Balance;
                                newFinalCost += newRepertory.FinalCost;
                            }

                            db.DataContext.repertories.Add(new repertory()
                            {
                                OrderNo = order.OrderNo,
                                ProductID = it.ProductID,
                                Quantity = it.Quantity,
                                Balance = balance,
                                Description = "调拨出",
                                CreatedOn = order.NoteDate,
                                Method = order.Method,
                                HouseID = order.HouseID,
                                Retention = it.Retention,
                                FinalCost = finalCost
                            });
                            db.DataContext.repertories.Add(new repertory()
                            {
                                OrderNo = newOrder.OrderNo,
                                ProductID = it.ProductID,
                                Quantity = it.Quantity,
                                Balance = newBalance,
                                Description = "调拨入",
                                CreatedOn = order.NoteDate,
                                Method = order.Method,
                                HouseID = targetHouseID,
                                Retention = it.Retention,
                                FinalCost = newFinalCost
                            });
                        }
                    }
                    #endregion

                    db.DataContext.SaveChanges();
                    order.ID = dOrder.ID;
                    return order;
                }
            }
            return null;
        }
        /// <summary>
        /// 查询单据明细列表
        /// </summary>
        /// <param name="sea"></param>
        /// <returns></returns>
        public static VProductOrderDetailsCollection GetOrderDetails(ProductOrderQuery sea)
        {
            var result = new VProductOrderDetailsCollection();
            using (DBCentre db = new DBCentre())
            {
                IQueryable<view_order_product_details> q = db.DataContext.view_order_product_details;
                if (sea != null)
                {
                    if (!string.IsNullOrEmpty(sea.OrderNo))
                        q = q.Where(p => p.OrderNo == sea.OrderNo || p.AssociatedDealNo==sea.OrderNo);
                    if (sea.CustomerID > 0)
                        q = q.Where(p => p.CustomerID == sea.CustomerID);
                    if (sea.OperatorUserID > 0)
                        q = q.Where(p => p.OperatorUserID == sea.OperatorUserID);
                    if (sea.OrderDateBefore != null)
                        q = q.Where(p => p.NoteDate.CompareTo(sea.OrderDateBefore.Value) >= 0);
                    if (sea.OrderDateAfter != null)
                        q = q.Where(p => p.NoteDate.CompareTo(sea.OrderDateAfter.Value) <= 0);
                    if (sea.Method  > 0)
                        q = q.Where(p => sea.Method == p.Method);
                    
                    if (sea.ProductID > 0)
                        q = q.Where(p => p.ProductID == sea.ProductID);
                }
                var n = q.Count();
                if (n > 0)
                {
                    //var sum = q.Sum(p => p.Quantity * p.UnitPrice);
                    q = q.OrderByDescending(p => p.ID);
                    if (sea != null && sea.PageSize > 0)
                        q = q.Skip(sea.PageSize * sea.PageIndex).Take(sea.PageSize);
                    var lst = q.ToList();
                    result = Convertor.ConvertCollection<VProductOrderDetailsModel, view_order_product_details, VProductOrderDetailsCollection>(lst);
                    result.TotalRecordsCount = n;
                    //result.Add(new VDealOrderDetailsModel() { OrderNo = "", ProductName = "金额汇总：", Quantity = 1, UnitPrice = sum, UnitName = "个" });
                }
            }
            return result;
        }
    }
}
